﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace ZFBActivation.Core
{
    #region 封装WPF属性

    public class MyCommMetoh
    {
        //得到属性的名称
        public static string GetPropertyName<T, U>(Expression<Func<T, U>> exp) {
            string _pName = "";
            if (exp.Body is MemberExpression) {
                _pName = (exp.Body as MemberExpression).Member.Name;
            } else if (exp.Body is UnaryExpression) {
                _pName = ((exp.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
            }
            return _pName;
        }
    }

    public class NotifyPropertyBase : INotifyPropertyChanged
    {
        /// <summary>
        /// Returns a dispatcher for multi-threaded scenarios
        /// </summary>
        /// <returns></returns>
        public static Dispatcher GetDispatcher(DispatcherObject source = null) {
            //use the application's dispatcher by default
            if (Application.Current != null) return Application.Current.Dispatcher;

            //fallback for WinForms environments
            if (source != null && source.Dispatcher != null) return source.Dispatcher;

            //ultimatively use the thread's dispatcher
            return Dispatcher.CurrentDispatcher;
        }

        #region INotifyPropertyChanged
        public void OnPropertyChanged(string propertyName) {
            if (PropertyChanged != null) {
                GetDispatcher().BeginInvoke((Action)delegate {
                    try {
                        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                    }
                    catch (Exception ex) {
                        var msg = string.Format("发送UI属性变化事件异常,属性名称: {0}, 异常详细信息: {1}", propertyName, ex.ToString());
                    }
                }
                );

            }
        }
        public void OnPropertyChanged<T>(Expression<Func<T>> expression) {
            if (PropertyChanged != null) {
                var propertyName = ((MemberExpression)expression.Body).Member.Name;
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
    }
    public static class NotifyPropertyBaseEx
    {
        public static void OnPropertyChanged<T, U>(this T npb, Expression<Func<T, U>> exp) where T : NotifyPropertyBase, new() {
            string _PropertyName = MyCommMetoh.GetPropertyName(exp);
            npb.OnPropertyChanged(_PropertyName);
        }
    }

    public class IPropertyChanged : NotifyPropertyBase, IDisposable
    {
        public IPropertyChanged() {
        }

        Dictionary<object, object> _ValueDictionary = new Dictionary<object, object>();

        #region 根据属性名得到属性值
        public T GetPropertyValue<T>(string propertyName, T defaultValue) {
            if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("invalid " + propertyName);
            object _propertyValue;
            if (!_ValueDictionary.TryGetValue(propertyName, out _propertyValue)) {
                _propertyValue = defaultValue;
                _ValueDictionary.Add(propertyName, _propertyValue);
            }
            return (T)_propertyValue;
        }
        #endregion

        public bool SetPropertyValue<T>(string propertyName, T value) {
            if (!_ValueDictionary.ContainsKey(propertyName) || _ValueDictionary[propertyName] != (object)value) {
                _ValueDictionary[propertyName] = value;
                OnPropertyChanged(propertyName);
                return true;
            }
            return false;
        }

        #region Dispose
        public void Dispose() {
            DoDispose();
        }
        ~IPropertyChanged() {
            DoDispose();
        }
        void DoDispose() {
            if (_ValueDictionary != null) {
                _ValueDictionary.Clear();
                _ValueDictionary = null;
            }
        }
        #endregion
    }
    public static class PropertyNotifyObjectEx
    {
        public static U GetValue<T, U>(this T t, Expression<Func<T, U>> exp, U defaultValue = default(U)) where T : IPropertyChanged {
            string _pN = MyCommMetoh.GetPropertyName(exp);
            return t.GetPropertyValue<U>(_pN, defaultValue);
        }

        public static bool SetValue<T, U>(this T t, Expression<Func<T, U>> exp, U value) where T : IPropertyChanged {
            string _pN = MyCommMetoh.GetPropertyName(exp);
            return t.SetPropertyValue<U>(_pN, value);
        }


    }

    #endregion
}
